package jude.java.framework.thread;

import java.util.ArrayList;
import java.util.List;

import jude.java.util.Utils;

public class ThreadPool extends ThreadGroup {
	private boolean isClosed = false; // 线程池是否关闭
	private List<Runnable> workQueue; // 工作队列
	private WorkThread[] threads;
	private int threadIndex;
	/**
	 * 没有任务运行时, 是否保持线程运行
	 * */
	private boolean holding;
	
	private static int ThreadPool = 1; 			// 线程池的id

	public ThreadPool(int poolSize) {
		this(poolSize, true);
	}
	
	public ThreadPool(int poolSize, boolean hold) {
		super("pool." + ThreadPool++); 			// 指定ThreadGroup的名称
		setDaemon(true); 						// 继承到的方法，设置是否守护线程池
		workQueue = new ArrayList<Runnable>(); // 创建工作队列
//		this.poolSize = poolSize;
		threads = new WorkThread[poolSize];
		this.holding = hold;
		if (hold) {
			for (int i = 0; i < poolSize; i++) {
				threads[i] = new WorkThread(threadIndex++);
				threads[i].start(); 				// 创建并启动线程,线程池数量是多少就创建多少个线程
			}
			Utils.sleep(1000);
		}
	}

	/** 向工作队列中加入一个新任务,由线程去执行该任务 */
	public synchronized void execute(Runnable task) {
		if (isClosed) {
			throw new IllegalStateException();
		}
		if (task != null) {
			workQueue.add(task);// 向队列中加入一个任务
			if (holding) {
				notify(); // 唤醒一个正在getTask()方法中待任务的线程
			} else {
				for (int i=0; i<threads.length; i++) {
					if (threads[i] == null || !threads[i].isAlive()) {
						threads[i] = new WorkThread(threadIndex++);
						threads[i].start();
						break;
					}
				}
			}
		}
	}

	/** 从工作队列中取出一个任务,线程会调用此方法 */
	private synchronized Runnable getTask(int threadId)
			throws InterruptedException {
		if (holding) {
			while (workQueue.size() == 0) {
				if (isClosed)
					return null;
				wait(); // 如果工作队列中没有任务,就等待任务
			}
		} else if (workQueue.size() == 0) {
//			System.out.println("线程" + threadId + "没有获得任务");
			return null;
		}
		return workQueue.remove(0);
	}

	/** 关闭线程池 */
	public void close() {
		if (!isClosed) {
			waitFinish();
			isClosed = true;
			workQueue.clear();
			interrupt(); // 中断线程池中的所有的线程,此方法继承自ThreadGroup类
		}
	}
	
	/**
	 * 如果有线程异常中止, 启动新线程代替
	 * */
	public synchronized void alignThread() {
		if (workQueue.size() > 0)
			for (int i = 0; i < threads.length; i++) {
				WorkThread thread = threads[i];
				if (!thread.isAlive()) {
					thread = new WorkThread(threadIndex++);
					thread.start();
					threads[i] = thread;
				}
			}
	}
	
	public int getPoolSize() {
		return threads == null ? 0 : threads.length;
	}

	/** 等待线程把所有任务执行完毕 */
	public void waitFinish() {
//		synchronized (this) {
			isClosed = true;
			if (holding)
				notifyAll(); // 唤醒所有还在getTask()方法中等待任务的线程
//		}
		Thread[] threads = new Thread[activeCount()]; // activeCount()返回该线程组中活动线程的估计值。
		int count = enumerate(threads); // enumerate()方法继承自ThreadGroup类，根据活动线程的估计值获得线程组中当前所有活动的工作线程
		for (int i = 0; i < count; i++) { // 等待所有工作线程结束
			try {
				threads[i].join(); // 等待工作线程结束
			} catch (InterruptedException ex) {
				ex.printStackTrace();
			}
		}
	}
	
	public void waitAllTask() throws InterruptedException {
		Utils.sleep(1000);
		while (!workQueue.isEmpty()) {
			Thread.sleep(3000);
		}
		close();
	}

	/**
	 * 内部类,工作线程,负责从工作队列中取出任务,并执行
	 */
	private class WorkThread extends Thread {
		private int id;

		public WorkThread(int id) {
			super(ThreadPool.this, ThreadPool.this.getName() + "-work." + id);
			this.id = id;
		}

		public void run() {
			while (!isInterrupted()) { // isInterrupted()方法继承自Thread类，判断线程是否被中断
				Runnable task = null;
				try {
					if (holding) {
						task = getTask(id);
					} else {
						int c = 3;
						while(c-- > 0) {
//							System.out.println(c);
							task = getTask(id);
//							System.out.println(c);
							if (task != null)
								break;
							Thread.sleep(1000);		//waiting for task 30s
						}
					}
				} catch (InterruptedException ex) {
					ex.printStackTrace();
				}
				if (task == null) {
					break;
				}

//				System.out.println("线程" + id + "开始执行任务...");
				try {
					task.run(); // 运行任务
				} catch (Throwable t) {
					t.printStackTrace();
				}
			}// end while
//			System.out.println("线程" + id + "结束运行");
		}
	}
	
}